<?php

namespace App\Service\Pay;

use App\Models\Bank;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Exception;
use Elliptic\EC;

class TarsPayService extends PayService implements Pay
{
    /**
     * 充值通知地址
     * @var string
     */
    protected string $pay_notify_url = '/api/v1/tars_recharge';

    /**
     * 代付通知地址
     * @var string
     */
    protected string $withdrawal_notify_url = '/api/v1/tars_withdrawal';

    protected string $api_url = "https://payment.tarspay.pro";

    //充值
    public function recharge($attach = [])
    {
        try {
            info($_SERVER['SERVER_ADDR'] );
            $this->setReturnUrl();
            $param = [
                'amount' => sprintf('%.2f', $this->order->amount / 100),
                'body' => 'buy card',
                'currency' => 'BRA',
                'mchNo' => $this->merchant,
                'mchOrderNo' => $this->order->no,
                'notifyUrl' => url($this->pay_notify_url),
                'subject' => 'recharge',
                'wayCode' => $this->pay_code
            ];
            $nonce = time() * 1000;
            $header = [
                "X-API-KEY" => $this->getPublicKey(),
                "X-API-NONCE" => $nonce,
                "X-API-SIGNATURE" => $this->sign($param,$nonce,$this->pay_url)
            ];
            $response = Http::withHeaders($header)->asJson()->post($this->api_url.$this->pay_url, $param);
            info($response);
            $result = json_decode($response->body(), true);
            $this->order->param = json_encode($param, JSON_UNESCAPED_UNICODE);
            $this->order->response = json_encode($result, JSON_UNESCAPED_UNICODE);
            if (isset($result['code']) && $result['code'] == '0') {
                $this->order->payment_no = $result['data']['payOrderId'];
                $this->order->save();
                return $result['data']['payUrl'];
            }
            $this->rechargeFail();
            return false;
        } catch (Exception $exception) {
            $error_message = json_encode(['msg' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine()], JSON_UNESCAPED_UNICODE);
            $this->rechargeFail($error_message);
            return false;
        }
    }

    public function withdrawal($attach = [])
    {
        //info('提现订单开始:'.$this->order->no);
        try {
            $card = json_decode($this->order->card, true);
            $param = [
                'mchNo' => $this->merchant,
                'mchOrderNo' => $this->order->no,
                'wayCode' => "PIX",
                'currency' => 'BRA',
                'amount' => sprintf('%.2f', $this->order->actual_amount / 100),
                'notifyUrl' => url($this->withdrawal_notify_url),
                'customerName' => $card['username'],
                'customerEmail' => $card['username']."@gmail.com",
                'customerContact' => $card['id'],
                'customerAccountNumber' => $card['number'],
                'bankName' => "PIX",
                'accountTax' => $card['number']
            ];

            $nonce = time() * 1000;
            $header = [
                "X-API-KEY" => $this->getPublicKey(),
                "X-API-NONCE" => $nonce,
                "X-API-SIGNATURE" => $this->sign($param,$nonce,$this->withdrawal_url)
            ];
            $response = Http::withHeaders($header)->asJson()->post($this->api_url.$this->withdrawal_url, $param);
            //info('提现订单响应:'.$response);
            $result = json_decode($response->body(), true);
            $result = is_array($result) ? $result : [];
            //记录入参跟响应
            $state = isset($result['code']) && $result['code'] == '0';
            if($state){
                $payOrderId = $result['data']['payOrderId'];
            }else{
                $payOrderId = "";
            }
            $this->withdrawalCallback($param, $result, $payOrderId, $state);
            $this->order->save();
        } catch (Exception $exception) {
            $this->withdrawalCallback([], ['msg' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine()], '', false);
        }
    }


    public function getPublicKey(): string
    {
        $ec = new EC('secp256k1');
        $key = $ec->keyFromPrivate($this->private_key);
        return $key->getPublic(true, 'hex');
    }

    /**
     * 签名
     * @param $data
     * @param $secret
     * @return string
     */
    protected function sign($data,$nonce,$path)
    {
        ksort($data);
        $result = [];
        foreach ($data as $key => $val) {
            array_push($result, $key . "=" . $val);
        }
        $sorted_data =  join("&", $result);

        $signstr = join("|", ["POST", $path, $nonce, $sorted_data]);

        $message = hash("sha256", hash("sha256", $signstr, True), True);
        $ec = new EC('secp256k1');
        $key = $ec->keyFromPrivate($this->private_key);
        $sign =  $key->sign(bin2hex($message))->toDER('hex');

        return $sign;
    }

    /**
     * 验签
     * @param array $params
     * @param string $type
     * @return bool
     */
    public function checkSign(array $params, string $sign): bool
    {
        $message = json_encode($params);
        $message = hash("sha256", hash("sha256", "$message", True), True);
        $ec = new EC('secp256k1');
        $key = $ec->keyFromPublic($this->public_key, "hex");
        return $key->verify(bin2hex($message), $sign);
    }



}
